package com.huan.groovy.utils;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.EncodingGroovyMethods;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.Map;

/**
 * groovy 工具类
 *
 * @author huan.fu
 * @date 2024/7/17 - 12:23
 */
@Component
public class GroovyUtils {

    private final GroovyClassLoader loader = new GroovyClassLoader();

    /**
     * 执行脚本
     *
     * @param script  脚本内容
     * @param context 上下文
     * @return T
     */
    public <T> T exec(String script, Map<Object, Object> context) {
        try {
            String fileName = "Script_" + EncodingGroovyMethods.md5(script) + ".groovy";
            GroovyCodeSource gcs = createCodeSource(() -> new GroovyCodeSource(script, fileName, "/groovy/script"));
            Class<?> clazz = loader.parseClass(gcs, true);
            Object instance = clazz.newInstance();
            Method method = clazz.getMethod("invoked", Map.class);
            Object invoke = method.invoke(instance, context);
            return (T) invoke;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static GroovyCodeSource createCodeSource(PrivilegedAction<GroovyCodeSource> action) {
        return java.security.AccessController.doPrivileged(action);
    }

}
